package de.duester.genealogy.model.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import de.duester.genealogy.Utility;
import de.duester.genealogy.model.Document;
import de.duester.genealogy.model.Event;
import de.duester.genealogy.model.Person;
import de.duester.genealogy.model.PersonDocument;
import de.duester.genealogy.model.PersonEvent;
import de.greenrobot.dao.DaoException;

public class PersonService {

	public static List<Event> getEvents(Person person) {
		List<Event> list = new ArrayList<Event>();
		try {
			for (PersonEvent pe : person.getPersonEvents())
				if (!list.contains(pe.getEvent()))
					list.add(pe.getEvent());
			Collections.sort(list, new Comparator<Event>() {

				@Override
				public int compare(Event lhs, Event rhs) {
					return lhs.compare(rhs);
				}
			});
		} catch (DaoException e) {
		}
		return list;
	}

	public static List<Event> getEvents(Person person, String typeCode) {
		List<Event> list = new ArrayList<Event>();
		List<Event> events = getEvents(person);
		for (Event event : events)
			if (event.getTypeCode().equals(typeCode))
				list.add(event);
		return list;
	}

	public static List<Event> getEvents(Person person, String typeCode, String roleCode) {
		List<Event> list = new ArrayList<Event>();
		List<Event> events = getEvents(person, typeCode);
		for (Event event : events)
			if (EventService.getPersons(event, roleCode).contains(person))
				list.add(event);
		return list;
	}

	public static List<Document> getDocuments(Person person) {
		List<Document> list = new ArrayList<Document>();
		try {
			for (PersonDocument pd : person.getPersonDocuments())
				if (!list.contains(pd.getDocument()))
					list.add(pd.getDocument());
		} catch (DaoException e) {
		}
		return list;
	}

	public static List<Document> getDocuments(Person person, int type) {
		List<Document> list = new ArrayList<Document>();
		List<Document> documents = getDocuments(person);
		for (Document document : documents)
			if (document.getType().equals(type))
				list.add(document);
		return list;
	}

	public static boolean isAlive(Person person) {
		return (getEvents(person, "death").size() == 0);
	}

	public static Person getFather(Person person) {
		List<Event> e = getEvents(person, "birth", "child");
		if (e.size() > 0)
			return EventService.getPerson(e.get(0), "father");
		else
			return null;
	}

	public static Person getMother(Person person) {
		List<Event> e = getEvents(person, "birth", "child");
		if (e.size() > 0)
			return EventService.getPerson(e.get(0), "mother");
		else
			return null;
	}

	public static List<Person> getSpouses(Person person) {
		List<Person> list = new ArrayList<Person>();

		String roleCode1, roleCode2;
		switch (person.getGender()) {
		case Person.MALE:
			roleCode1 = "husband";
			roleCode2 = "wife";
			break;
		case Person.FEMALE:
			roleCode1 = "wife";
			roleCode2 = "husband";
			break;
		default:
			roleCode1 = roleCode2 = "";
			break;
		}
		List<Event> events = getEvents(person, "marriage", roleCode1);
		for (Event e : events)
			list.add(EventService.getPerson(e, roleCode2));

		return list;
	}

	public static List<Person> getChildren(Person person) {
		String roleCode;
		switch (person.getGender()) {
		case Person.MALE:
			roleCode = "father";
			break;
		case Person.FEMALE:
			roleCode = "mother";
			break;
		default:
			roleCode = "";
			break;
		}

		List<Event> e = getEvents(person, "birth", roleCode);
		List<Person> children = new ArrayList<Person>();

		for (Event event : e) {
			Person child = EventService.getPerson(event, "child");
			children.add(child);
		}

		return children;
	}

	public static List<Person> getChildren(Person person1, Person person2) {
		List<Person> list = new ArrayList<Person>();

		List<Person> children = getChildren(person1);
		for (Person child : children) {
			Person parent2 = null;
			switch (person2.getGender()) {
			case Person.MALE:
				parent2 = getFather(child);
				break;
			case Person.FEMALE:
				parent2 = getMother(child);
				break;
			default:
				break;
			}
			if (person2.equals(parent2))
				list.add(child);
		}

		return list;
	}

	public static List<Person> getPersonsByGender(int gender, Person toExclude) {
		List<Person> list;
		List<Person> persons = Utility.getDaoSession().getPersonDao().loadAll();
		if (gender == Person.ALL)
			list = persons;
		else {
			list = new ArrayList<Person>();
			for (Person p : persons)
				if (p.getGender() == gender)
					list.add(p);
		}
		if (toExclude != null)
			list.remove(toExclude);
		return list;
	}
}
